<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>推流页面</title>
  </head>

  <body>
    <video id="localStream" style="width: 320px; height: 240px;" autoplay muted></video>
    <select id="encoder_select"></select>
    <script>
      // 获取摄像头返回的MediaStream
      let localStream = null;

      // 显示本地画面的VideoElement
      let localVideo = document.getElementById("localStream");

      let encoder_select = document.getElementById("encoder_select");

      encoder_select.addEventListener('change', () => {
        let codec = JSON.parse(encoder_select.options[encoder_select.selectedIndex].value);
        let sender = pc_pub.getSenders()[0];
        let param = sender.getParameters();
        param.encodings[0].codec = codec;
        sender.setParameters(param).then(() => {
          console.log("change encoder suc");
        }).catch((err) => {
          console.log("change encoder fail");
        })
      })

      // 建立连接按钮
      let startBtn = document.getElementById("startBtn");

      // 推流用的MediaStream
      let pc_pub = new RTCPeerConnection();

      let ws = new WebSocket('ws://127.0.0.1:9000');
      ws.addEventListener('open', () => {
        // 通知server pub已经上线
        ws.send(JSON.stringify({
          type: "publish"
        }))
      })

      ws.addEventListener('message', (event) => {
        let msg = JSON.parse(event.data);
        switch (msg.type) {
          case "start":
            start();
            break;

          case "answer":
            pc_pub.setRemoteDescription(msg).then(() => {

            }).catch((err) => {

            })
            break;

          default:
            pc_pub.addIceCandidate(msg);
            break;
        }
      })

      pc_pub.addEventListener('icecandidate', (event) => {
        if (event.candidate) {
          ws.send(JSON.stringify(event.candidate));
        }
      })

      pc_pub.addEventListener("iceconnectionstatechange", () => {
        if ('connected' == pc_pub.iceConnectionState) {
          encoder_select.options.length = 0;
          let sender = pc_pub.getSenders()[0];
          let param = sender.getParameters();
          console.log(param.codecs)
          for (let i = 0; i < param.codecs.length; ++i) {
            if (param.codecs[i].mimeType === "video/VP8" 
                || param.codecs[i].mimeType === "video/VP9" 
                || param.codecs[i].mimeType === "video/AV1"
                || param.codecs[i].mimeType === "video/H264") {
              let label = param.codecs[i].sdpFmtpLine ? `${param.codecs[i].mimeType} ${param.codecs[i].sdpFmtpLine}` : `${param.codecs[i].mimeType}`;
              encoder_select.add(new Option(label, JSON.stringify(param.codecs[i])))
            }
          }
        }
      })

      function start() {
        getDevice().then((mediaStream) => {
          pc_pub.addTrack(mediaStream.getVideoTracks()[0], mediaStream);
          pc_pub.createOffer().then((offer) => {
            pc_pub.setLocalDescription(offer).then(() => {
              ws.send(JSON.stringify(offer));
            }).catch((err) => {
              console.error('setLocalDescription error', err);
            })
          }).catch((err) => {
            console.error("create offer error", err);
          })
        }).catch((err) => {
          console.error("getDevice error", err);
        })
      }

      function getDevice() {
        return new Promise((resolve, reject) => {
          navigator.mediaDevices.getUserMedia({ video: true }).then((mediaStream) => {
            localVideo.srcObject = mediaStream;
            resolve(mediaStream);
          }).catch((err) => {
            reject(err);
          })
        })
      }
    </script>
  </body>
</html>